#pragma once
#ifndef __G_OPENCVTOOLS_PROGRAM__
#define __G_OPENCVTOOLS_PROGRAM__

#include <Windows.h>
#include <tchar.h>
#include "opencv2/opencv.hpp"
#include "Common.h"

using namespace cv;

struct MatTemplate
{
    int state;// mat对应阶段
    Mat matData;//mat数据
    float poi;//匹配精度
    int conditionState;//返回条件状态
};

// 当前状态阶段
enum class NowState
{
    NOWSTATE_NONE,

    NOWSTATE_MAIN_TANSUO,// 探索主界面
    NOWSTATE_YUHUN_SWITCH,// 御魂玩法选择界面
    NOWSTATE_YUHUN_TYPE,// 御魂挑战类型选择（组队-挑战）
    NOWSTATE_YUHUN_ATTACK_ZHUNBEI,// 战斗准备界面
    NOWSTATE_YUHUN_ATTACK,// 战斗界面
    NOWSTATE_YUHUN_JIESUAN_CONDITION,//判断战斗结果阶段
    NOWSTATE_YUHUN_JIESUAN_Win,// 战斗结算界面（胜利）
    NOWSTATE_YUHUN_JIESUAN_Lower,// 战斗结算界面（失败）

    NOWSTATE_MAX,// 完结（停止执行脚本）
};

class OpenCVTools
{
public:
	OpenCVTools();
	~OpenCVTools();

    static OpenCVTools* instance()
    {
        static OpenCVTools instance;
        return &instance;
    }

    // 后台截图
	static Mat hwnd2mat(HWND hwnd);

	// 通过pid获取窗口句柄
	static HWND GetHwndByPid(DWORD dwProcessID);

    // 点击鼠标（点击模式）
	static int MouseClick(int nMode);

	// 发送模拟鼠标点击消息
	static void PostMouseClickMessage(HWND hwnd, int x, int y);

	// 滑动鼠标（按住左键从X,Y 移动到 DX,DY）

	// 模板匹配（通过提供模板来判断是否是所处模板状态，是则返回找到的Mat）
	static int MatchTemplateFromTmp(Mat NowImg, Mat tmpImg, Mat& result, float poi);

	// 获取屏幕缩放比
	static double GetMonitorScale();

	// 移动鼠标到指定位置
	static void Mouse_Move(int x, int y);

	// 移动鼠标到指定位置
	static int MoveMouse(unsigned int dx, unsigned int dy);

	// 注册预加载模板。每个状态可设置多个检测条件，必须都符合才过。
    void RegisterMatchMatTemplate(int state, Mat matTemplate, float poi, int resState);

    // 注册条件判断加载模板。每个状态可设置多个检测条件，必须其中有一个符合才过。
    void RegisterConditionMatchMatTemplate(int state, Mat matTemplate, float poi, int resState);

    // 注册阶段对应鼠标点击模板(每个阶段只能注册一个鼠标点击模板，重复注册替换之前的，如果该状态无对应mat。则不点击)
    void RegisterMatchMatMouseClick(int state, Mat matTemplate, float poi);

	// 进入休息状态
    void StartRepose(int reposeTime) { ReposeTime = reposeTime; };

	// 结束休息状态
    void EndRepose() { ReposeTime = 0; };

    // 从状态匹配模板（返回-1代表匹配失败.否则返回注册模板时注册的返回状态.本模板为多条件必须全部符合，因此注册的返回状态必须保持一致。否则不保证按照设计返回）
    int MatchTemplateFromState(int state, Mat NowImg);

    // 从状态匹配条件模板（返回-1代表匹配失败.否则返回注册模板时注册的返回状态）
    int MatchTemplateConditionFromState(int state, Mat NowImg);

    // 从状态点击坐标
    bool MouseClickFromMatchTemplateState(int state, Mat NowImg);

    // 是否休息状态
    bool IsRepose(int diffTime)
    {
        if (ReposeTime > 0)
        {
            ReposeTime -= diffTime;
            return true;
        } 

        return false;
    };

private:
    std::vector<MatTemplate>_MatchTemplateMatVec;//每个状态可设置多个检测条件，必须都符合才过。
    std::vector<MatTemplate>_MatchTemplateMatConditionVec;//条件判断。每个状态可设置多个检测条件，必须其中有一个符合才过。
    std::unordered_map<int, MatTemplate>_MatchTemplateMatMouseClickMap;//每个状态对应一个鼠标点击坐标。如果该状态无对应mat。则不点击
    HWND OpenCVToolBindHwnd;//绑定的窗口句柄
    int CurState;//当前阶段
    int ReposeTime;//休息时间
};

#endif
